﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using UtilZ.Dotnet.Ex.Base;
using UtilZ.Dotnet.Ex.Log;

namespace ConAppCore.Test
{
    internal class TestEnumerableEx
    {
        public static void Test()
        {
            try
            {

                //Int16 a = Int16.MinValue;
                //var a2 = a * -1;
                //var a3 = (Int16)a2;

                //Int16 b = Int16.MaxValue;
                //var b2 = b * -1;
                //var b3 = (Int16)b2;

                //int c = 40000;
                //var c3 = (Int16)c;

                //TestMaxPer();
                TestAvgPer();

                //TestIQMerge1();
                //TestIQMerge2();
                //TestIQMerge3();

                //TestRealToComplex();
                //TestComplexToReal();

                //TestMaxMin();
                //TestMinMax();
                //TestAvg();
            }
            catch (Exception ex)
            {
                Loger.Error(ex);
            }
        }

        private static void TestAvg()
        {
            byte[] byteArr = new byte[] { 1, 2, 3, 4 };
            var byteAvg = EnumerableEx.Average(byteArr, 1, 2);

            sbyte[] sbyteArr = new sbyte[] { -1, -2, 3, 4 };
            var sbyteAvg = EnumerableEx.Average(sbyteArr, 1, 2);

            short[] shortArr = new short[] { -1, -2, 3, 4 };
            var shortAvg = EnumerableEx.Average(shortArr, 1, 2);

            ushort[] ushortArr = new ushort[] { 1, 2, 3, 4 };
            var ushortAvg = EnumerableEx.Average(ushortArr, 1, 2);

            int[] intArr = new int[] { -1, -2, 3, 4 };
            var intAvg = EnumerableEx.Average(intArr, 1, 2);

            uint[] uintArr = new uint[] { 1, 2, 3, 4 };
            var uintAvg = EnumerableEx.Average(uintArr, 1, 2);

            long[] longArr = new long[] { -1, -2, 3, 4 };
            var longAvg = EnumerableEx.Average(longArr, 1, 2);

            ulong[] ulongArr = new ulong[] { 1, 2, 3, 4 };
            var ulongAvg = EnumerableEx.Average(ulongArr, 1, 2);

            float[] floatArr = new float[] { -1, -2, 3, 4 };
            var floatAvg = EnumerableEx.Average(floatArr, 1, 2);

            double[] doubleArr = new double[] { -1, -2, 3, 4 };
            var doubleAvg = EnumerableEx.Average(doubleArr, 1, 2);

            decimal[] decimalArr = new decimal[] { -1, -2, 3, 4 };
            var decimalAvg = EnumerableEx.Average(decimalArr, 1, 2);

            Half[] halfArr = new Half[] { (Half)(-1), (Half)(-2), (Half)3, (Half)4 };
            var halfAvg = EnumerableEx.Average(halfArr, 1, 2);
        }

        private static void TestMinMax()
        {
            byte[] byteArr = new byte[] { 1, 2, 3, 4 };
            byte byteMin, byteMax;
            EnumerableEx.MinMax(byteArr, 1, 2, out byteMin, out byteMax);

            sbyte[] sbyteArr = new sbyte[] { -1, -2, 3, 4 };
            sbyte sbyteMin, sbyteMax;
            EnumerableEx.MinMax(sbyteArr, 1, 2, out sbyteMin, out sbyteMax);

            short[] shortArr = new short[] { -1, -2, 3, 4 };
            short shortMin, shortMax;
            EnumerableEx.MinMax(shortArr, 1, 2, out shortMin, out shortMax);

            ushort[] ushortArr = new ushort[] { 1, 2, 3, 4 };
            ushort ushortMin, ushortMax;
            EnumerableEx.MinMax(ushortArr, 1, 2, out ushortMin, out ushortMax);

            int[] intArr = new int[] { -1, -2, 3, 4 };
            int intMin, intMax;
            EnumerableEx.MinMax(intArr, 1, 2, out intMin, out intMax);

            uint[] uintArr = new uint[] { 1, 2, 3, 4 };
            uint uintMin, uintMax;
            EnumerableEx.MinMax(uintArr, 1, 2, out uintMin, out uintMax);

            long[] longArr = new long[] { -1, -2, 3, 4 };
            long longMin, longMax;
            EnumerableEx.MinMax(longArr, 1, 2, out longMin, out longMax);

            ulong[] ulongArr = new ulong[] { 1, 2, 3, 4 };
            ulong ulongMin, ulongMax;
            EnumerableEx.MinMax(ulongArr, 1, 2, out ulongMin, out ulongMax);

            float[] floatArr = new float[] { -1, -2, 3, 4 };
            float floatMin, floatMax;
            EnumerableEx.MinMax(floatArr, 1, 2, out floatMin, out floatMax);

            double[] doubleArr = new double[] { -1, -2, 3, 4 };
            double doubleMin, doubleMax;
            EnumerableEx.MinMax(doubleArr, 1, 2, out doubleMin, out doubleMax);

            decimal[] decimalArr = new decimal[] { -1, -2, 3, 4 };
            decimal decimalMin, decimalMax;
            EnumerableEx.MinMax(decimalArr, 1, 2, out decimalMin, out decimalMax);
        }

        private static void TestMaxMin()
        {
            byte[] byteArr = new byte[] { 1, 2, 3, 4 };
            byte byteMin = EnumerableEx.Min(byteArr, 1, 2);
            byte byteMax = EnumerableEx.Max(byteArr, 1, 2);

            sbyte[] sbyteArr = new sbyte[] { -1, -2, 3, 4 };
            sbyte sbyteMin = EnumerableEx.Min(sbyteArr, 1, 2);
            sbyte sbyteMax = EnumerableEx.Max(sbyteArr, 1, 2);

            short[] shortArr = new short[] { -1, -2, 3, 4 };
            short shortMin = EnumerableEx.Min(shortArr, 1, 2);
            short shortMax = EnumerableEx.Max(shortArr, 1, 2);

            ushort[] ushortArr = new ushort[] { 1, 2, 3, 4 };
            ushort ushortMin = EnumerableEx.Min(ushortArr, 1, 2);
            ushort ushortMax = EnumerableEx.Max(ushortArr, 1, 2);

            int[] intArr = new int[] { -1, -2, 3, 4 };
            int intMin = EnumerableEx.Min(intArr, 1, 2);
            int intMax = EnumerableEx.Max(intArr, 1, 2);

            uint[] uintArr = new uint[] { 1, 2, 3, 4 };
            uint uintMin = EnumerableEx.Min(uintArr, 1, 2);
            uint uintMax = EnumerableEx.Max(uintArr, 1, 2);

            long[] longArr = new long[] { -1, -2, 3, 4 };
            long longMin = EnumerableEx.Min(longArr, 1, 2);
            long longMax = EnumerableEx.Max(longArr, 1, 2);

            ulong[] ulongArr = new ulong[] { 1, 2, 3, 4 };
            ulong ulongMin = EnumerableEx.Min(ulongArr, 1, 2);
            ulong ulongMax = EnumerableEx.Max(ulongArr, 1, 2);

            float[] floatArr = new float[] { -1, -2, 3, 4 };
            float floatMin = EnumerableEx.Min(floatArr, 1, 2);
            float floatMax = EnumerableEx.Max(floatArr, 1, 2);

            double[] doubleArr = new double[] { -1, -2, 3, 4 };
            double doubleMin = EnumerableEx.Min(doubleArr, 1, 2);
            double doubleMax = EnumerableEx.Max(doubleArr, 1, 2);

            decimal[] decimalArr = new decimal[] { -1, -2, 3, 4 };
            decimal decimalMin = EnumerableEx.Min(decimalArr, 1, 2);
            decimal decimalMax = EnumerableEx.Max(decimalArr, 1, 2);

        }

        private static void TestComplexToReal()
        {
            Complex[] complexes = new Complex[10];
            for (int i = 0; i < complexes.Length; i++)
            {
                complexes[i] = new Complex(i + 1, 0d);
            }

            double[] realDatas = new double[6];
            EnumerableEx.ComplexToReal(complexes, realDatas);

            double[] realDatas2 = new double[8];
            // AlgorithmHelper.ComplexToReal(complexes, 2, realDatas2, 1, 5);
            EnumerableEx.ComplexToReal(complexes, 2, realDatas2, 2, 4);
        }

        private static void TestRealToComplex()
        {
            double[] realDatas = new double[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            Complex[] complexes = new Complex[6];
            EnumerableEx.RealToComplex(realDatas, complexes);


            Complex[] complexes2 = new Complex[8];
            EnumerableEx.RealToComplex(realDatas, 2, complexes2, 1, 5);
            //AlgorithmHelper.RealToComplex(realDatas, 2, complexes2, 2, 4);
        }


        private static void TestIQMerge3()
        {
            int count = 2001;
            double[] iDatas = new double[count];
            double[] qDatas = new double[count];
            double iData, qData;
            bool flag = true;
            for (int i = 0; i < count; i++)
            {
                if (flag)
                {
                    iData = i + 1;
                    qData = i + 100001;
                }
                else
                {
                    iData = i + 100001;
                    qData = i + 1;
                }

                iDatas[i] = iData;
                qDatas[i] = qData;
                flag = !flag;
            }

            double[] realDatas = new double[count * 3];
            //var ret2 = SignalHelper.IQToReal(iDatas, qDatas);
            //string str2 = string.Join(',', ret2);
            int sourceIndex = 10;
            EnumerableEx.IQMerge(iDatas, qDatas, sourceIndex, realDatas, iDatas.Length, iDatas.Length - sourceIndex);
            string str2 = string.Join(',', realDatas);
        }

        private static void TestIQMerge2()
        {
            Complex[] datas = new Complex[2001];
            //Complex[] datas = new Complex[9];
            double iData, qData;
            bool flag = true;
            for (int i = 0; i < datas.Length; i++)
            {
                if (flag)
                {
                    iData = i + 1;
                    qData = i + 100001;
                }
                else
                {
                    iData = i + 100001;
                    qData = i + 1;
                }

                datas[i] = new Complex(iData, qData);
                flag = !flag;
            }

            var ret1 = EnumerableEx.IQMerge(datas);
            string str1 = string.Join(',', ret1);
            //double[] realDatas1 = new double[datas.Length * 3];
            //int sourceIndex1 = 0;
            ////SignalHelper.IQToReal(datas, sourceIndex1, realDatas1, datas.Length, datas.Length - sourceIndex1);
            //SignalHelper.IQToReal(datas, sourceIndex1, realDatas1, 4, datas.Length - 2);
            //string str1 = string.Join(',', realDatas1);
        }

        private static void TestIQMerge1()
        {
            Complex[] datas = new Complex[]
            {
                 new Complex(1,2),
                 new Complex(3,4),
                 new Complex(5,6),
                 new Complex(7,8),
                 new Complex(9,10),
                 new Complex(11,12),
                 new Complex(13,14),
                 new Complex(15,16),
            };
            //1,-4,-5,8,9,-12,-13,16
            //var ret1 = SignalHelper.IQToReal(datas);
            //string str1 = string.Join(',', ret1);
            double[] realDatas1 = new double[datas.Length * 3];
            int sourceIndex1 = 0;
            //SignalHelper.IQToReal(datas, sourceIndex1, realDatas1, datas.Length, datas.Length - sourceIndex1);
            EnumerableEx.IQMerge(datas, sourceIndex1, realDatas1, 4, datas.Length - 2);
            string str1 = string.Join(',', realDatas1);

            double[] iDatas = new double[] { 1, 3, 5, 7, 9, 11, 13, 15 };
            double[] qDatas = new double[] { 2, 4, 6, 8, 10, 12, 14, 16 };
            double[] realDatas = new double[qDatas.Length * 3];
            //var ret2 = SignalHelper.IQToReal(iDatas, qDatas);
            //string str2 = string.Join(',', ret2);
            //int sourceIndex = 0;
            //SignalHelper.IQToReal(iDatas, qDatas, sourceIndex, realDatas, iDatas.Length, iDatas.Length - sourceIndex);
            //string str2 = string.Join(',', realDatas);
        }



        private static void TestAvgPer()
        {
            //byte a = 150;
            //float mul = 2.0f;
            //var ret = a * mul;
            //byte b = (byte)ret;


            double[] source = new double[10000000];
            Random rnd = new Random();
            for (int i = 0; i < source.Length; i++)
            {
                source[i] = rnd.NextDouble() * 10000;
            }

            int testCount = 100;
            double avgRet, sum;
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Restart();

            for (int i = 0; i < testCount; i++)
            {
                avgRet = source.Average();
            }
            stopwatch.Stop();
            Console.WriteLine($"avg系统:{stopwatch.Elapsed.TotalMilliseconds}ms");


            stopwatch.Restart();
            for (int i = 0; i < testCount; i++)
            {
                sum = 0d;
                for (int j = 0; j < source.Length; j++)
                {
                    sum += source[i];
                }
                avgRet = sum / source.Length;
            }
            stopwatch.Stop();
            Console.WriteLine($"avg单向:{stopwatch.Elapsed.TotalMilliseconds}ms");


            stopwatch.Restart();
            int leftIndex, rightIndex;
            for (int i = 0; i < testCount; i++)
            {
                sum = 0d;
                leftIndex = 0;
                rightIndex = source.Length - 1;
                while (leftIndex < rightIndex)
                {
                    sum += source[leftIndex++];
                    sum += source[rightIndex--];
                }
                avgRet = sum / source.Length;
            }
            stopwatch.Stop();
            Console.WriteLine($"avg双向:{stopwatch.Elapsed.TotalMilliseconds}ms");


            Console.WriteLine("*****************************************************");


            int startIndex = 1000;
            int count = source.Length - startIndex;

            stopwatch.Restart();
            for (int i = 0; i < testCount; i++)
            {
                avgRet = source.Skip(startIndex).Take(count).Average();
            }
            stopwatch.Stop();
            Console.WriteLine($"avg系统2:{stopwatch.Elapsed.TotalMilliseconds}ms");


            stopwatch.Restart();
            int end;
            for (int i = 0; i < testCount; i++)
            {
                end = startIndex + count;
                sum = 0d;
                for (int j = startIndex; j < end; j++)
                {
                    sum += source[i];
                }
                avgRet = sum / source.Length;
            }
            stopwatch.Stop();
            Console.WriteLine($"avg单向2:{stopwatch.Elapsed.TotalMilliseconds}ms");


            stopwatch.Restart();
            for (int i = 0; i < testCount; i++)
            {
                sum = 0d;
                leftIndex = startIndex;
                rightIndex = startIndex + count - 1;
                while (leftIndex < rightIndex)
                {
                    sum += source[leftIndex++];
                    sum += source[rightIndex--];
                }
                avgRet = sum / source.Length;
            }
            stopwatch.Stop();
            Console.WriteLine($"avg双向2:{stopwatch.Elapsed.TotalMilliseconds}ms");

        }


        private static void TestMaxPer()
        {
            //byte a = 150;
            //float mul = 2.0f;
            //var ret = a * mul;
            //byte b = (byte)ret;


            double[] source = new double[10000000];
            Random rnd = new Random();
            for (int i = 0; i < source.Length; i++)
            {
                source[i] = rnd.NextDouble() * 10000;
            }

            int testCount = 100;
            double maxRet;
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Restart();
            for (int i = 0; i < testCount; i++)
            {
                maxRet = source.Max();
            }
            stopwatch.Stop();
            Console.WriteLine($"系统:{stopwatch.Elapsed.TotalMilliseconds}ms");


            stopwatch.Restart();
            for (int i = 0; i < testCount; i++)
            {
                maxRet = double.MinValue;
                for (int j = 0; j < source.Length; j++)
                {
                    if (source[i] > maxRet)
                    {
                        maxRet = source[i];
                    }
                }
            }
            stopwatch.Stop();
            Console.WriteLine($"单向:{stopwatch.Elapsed.TotalMilliseconds}ms");


            stopwatch.Restart();
            int leftIndex, rightIndex;
            for (int i = 0; i < testCount; i++)
            {

                maxRet = double.MinValue;
                leftIndex = 0;
                rightIndex = source.Length - 1;
                while (leftIndex < rightIndex)
                {
                    if (source[leftIndex] > maxRet)
                    {
                        maxRet = source[leftIndex];
                    }

                    if (source[rightIndex] > maxRet)
                    {
                        maxRet = source[rightIndex];
                    }

                    leftIndex++;
                    rightIndex--;
                }
            }
            stopwatch.Stop();
            Console.WriteLine($"双向:{stopwatch.Elapsed.TotalMilliseconds}ms");


            Console.WriteLine("*****************************************************");


            int startIndex = 1000;
            int count = source.Length - startIndex;

            stopwatch.Restart();
            for (int i = 0; i < testCount; i++)
            {
                maxRet = source.Skip(startIndex).Take(count).Max();
            }
            stopwatch.Stop();
            Console.WriteLine($"系统2:{stopwatch.Elapsed.TotalMilliseconds}ms");


            stopwatch.Restart();
            int end;
            for (int i = 0; i < testCount; i++)
            {
                maxRet = double.MinValue;
                end = startIndex + count;
                for (int j = startIndex; j < end; j++)
                {
                    if (source[i] > maxRet)
                    {
                        maxRet = source[i];
                    }
                }
            }
            stopwatch.Stop();
            Console.WriteLine($"单向2:{stopwatch.Elapsed.TotalMilliseconds}ms");


            stopwatch.Restart();
            for (int i = 0; i < testCount; i++)
            {

                maxRet = double.MinValue;
                leftIndex = startIndex;
                rightIndex = startIndex + count - 1;
                while (leftIndex < rightIndex)
                {
                    if (source[leftIndex] > maxRet)
                    {
                        maxRet = source[leftIndex];
                    }

                    if (source[rightIndex] > maxRet)
                    {
                        maxRet = source[rightIndex];
                    }

                    leftIndex++;
                    rightIndex--;
                }
            }
            stopwatch.Stop();
            Console.WriteLine($"双向2:{stopwatch.Elapsed.TotalMilliseconds}ms");

        }




    }
}
